home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Dev / misc / temgen.lha / Temgen / tg-0.11 / output.c < prev    next >
C/C++ Source or Header  |  2002-12-18  |  6KB  |  253 lines

  1. #include "alloc.h"
  2. #include "atom.h"
  3. #include "debug.h"
  4. #include "generator.h"
  5. #include "hash.h"
  6. #include "sysdefs.h"
  7.  
  8. struct txtline {
  9.     char  type;     /* t (text), e (embed) */
  10.     union txt_val {
  11.         char *text;
  12.         int   emb;
  13.     } val;
  14. };
  15.  
  16. struct outfile {
  17.     int                name;
  18.     int                embed;           /* 1 if the outfile is embed handle */
  19.     FILE              *f;
  20.     struct txtline    *data; 
  21.     int                count, size;
  22. };
  23.  
  24. static struct outfile *curout = NULL;
  25. static struct hash *otab = NULL;
  26. static int cur_name = 0;
  27. static int cur_embed = 0;
  28.  
  29. /* embed points stack */
  30. struct eps_item {
  31.     int embed, name;
  32. };
  33.  
  34. static struct eps_item *eps_stack = NULL;
  35. static int eps_size = 0; 
  36. static int eps_count = 0;
  37.  
  38. static void out_error( void )
  39. {
  40.     char buf[ 256 ];
  41.     snprintf( buf, sizeof(buf), "error generating output: %s", strerror(errno) );
  42.     fatal( buf );
  43. }
  44.  
  45. static unsigned ot_hfun( const void *p )
  46. {
  47.     return (unsigned)((const struct outfile*)p)->name;
  48. }
  49.  
  50. static int ot_cmp( const void *p1, const void *p2 )
  51. {
  52.     int n1, n2;
  53.     n1 = (((const struct outfile*)p1)->name << 1) 
  54.         | (((const struct outfile*)p1)->embed ? 1: 0);
  55.     n2 = (((const struct outfile*)p2)->name << 1)
  56.         | (((const struct outfile*)p2)->embed ? 1: 0);
  57.     return n1-n2;
  58. }
  59.  
  60. static struct outfile *newof( int name, int isembed )
  61. {
  62.     struct outfile *of;
  63.     
  64.     of = (struct outfile*)CALLOC( 1, sizeof(*of) );
  65.     if ( of ) {
  66.         of->name = name;
  67.         of->embed = (isembed ? 1: 0);
  68.         if ( !otab ) otab = new_hash( 37, ot_hfun, ot_cmp );
  69.         if ( h_add( otab, of ) ) {
  70.             FREE( of );
  71.             return NULL;
  72.         }
  73.     }
  74.     
  75.     return of;
  76. }
  77.  
  78. static struct outfile *findof( int name, int embed )
  79. {
  80.     struct outfile f, *of;
  81.     
  82.     f.name = name;
  83.     f.embed = (embed ? 1: 0);
  84.     of = (struct outfile*)h_get( otab, &f );
  85.     if ( !of ) of = newof( name, embed );
  86.     return of;
  87. }
  88.  
  89. void setout( int name, int embed )
  90. {
  91.     struct outfile *of;
  92.     
  93.     of = findof( name, embed );
  94.     if ( of ) {
  95.         curout = of;
  96.         cur_name = name;
  97.         cur_embed = embed;
  98.     } else
  99.         out_error();
  100. }
  101.  
  102. void push_out( void )
  103. {
  104.     while ( eps_count >= eps_size ) {
  105.         eps_size += 64;
  106.         eps_stack = (struct eps_item*)REALLOC( eps_stack, 
  107.                 eps_size*sizeof( eps_stack[0] ) );
  108.         if ( !eps_stack ) fatal( "memory allocation error" );
  109.     }
  110.     
  111.     eps_stack[ eps_count ].name = cur_name;
  112.     eps_stack[ eps_count ].embed = cur_embed;
  113.     eps_count++;
  114. }
  115.  
  116. void pop_out( void )
  117. {
  118.     if ( eps_count <= 0 ) return;
  119.     cur_name = eps_stack[ --eps_count ].name;
  120.     cur_embed = eps_stack[ eps_count ].embed;
  121.     setout( cur_name, cur_embed );
  122. }
  123.  
  124. static struct txtline *nextline( void )
  125. {
  126. #define  TABDELTA    1024        /* TODO tune */
  127.     if ( !curout ) setout( atom("stdout"), 0 );
  128.     if ( !curout ) out_error();
  129.     if ( curout->size <= curout->count ) {
  130.         struct txtline *old = curout->data;
  131.         curout->size += TABDELTA;
  132.         curout->data = (struct txtline*)REALLOC( old,
  133.                 curout->size * sizeof( curout->data[0] ));
  134.         if ( !curout->data ) {
  135.             curout->data = old;
  136.             curout->size -= TABDELTA;
  137.             return NULL;
  138.         }
  139.     }
  140.     
  141.     return curout->data + curout->count++;
  142. }
  143.  
  144. void writeout( const char *s )
  145. {
  146.     struct txtline *tl;
  147.     
  148.     tl = nextline();
  149.     if ( !tl ) out_error();
  150.     
  151.     tl->type = 't';
  152.     tl->val.text = STRDUP( s );
  153.     if ( debugger ) debout( "OUT:%s", s ); 
  154.     if ( !tl->val.text ) out_error();
  155. }
  156.  
  157. void embed( int id )
  158. {
  159.     struct txtline *tl;
  160.     
  161.     tl = nextline();
  162.     if ( !tl ) out_error();
  163.     
  164.     tl->type = 'e';
  165.     tl->val.emb = id;
  166. }
  167.  
  168. void setemb( int id )
  169. {
  170.     setout( id, 1 );
  171. }
  172.  
  173. static int do_fopen( struct outfile *of )
  174. {
  175.     if ( !of ) return -1;
  176.     if ( of->embed ) return 0;
  177.     if ( of->name == atom("stdout") )
  178.         of->f = stdout;
  179.     else if ( of->name == atom("stderr"))
  180.         of->f = stderr;
  181.     else
  182.         of->f = fopen( atom_name(of->name), "w" );
  183.     return of->f < 0;
  184. }
  185.  
  186. static int writeln( struct outfile*, struct txtline* );
  187.  
  188. static int doembed( struct outfile *of, int id )
  189. {
  190.     int i;
  191.     struct outfile *em;
  192.     em = findof( id, 1 );
  193.  
  194.     for ( i=0; i<em->count; i++ ) 
  195.         if ( writeln( of, em->data + i ) ) return -1;
  196.     
  197.     return 0; 
  198. }
  199.  
  200. static int writeln( struct outfile *of, struct txtline *tl )
  201. {
  202.     switch( tl->type ) {
  203.         case 'e':
  204.             return doembed( of, tl->val.emb );
  205.         case 't':
  206.             if ( !of->f ) do_fopen( of );
  207.             if ( !of->f ) {
  208.                     char buf[ 512 ];
  209.                     snprintf( buf, sizeof(buf), "error creating %s: %s",
  210.                                     atom_name(of->name), strerror(errno) );
  211.                     fatal( buf );
  212.             }
  213.  
  214.             return fputs( tl->val.text, of->f ) < 0;
  215.     }
  216.     
  217.     return -1;
  218. }
  219.  
  220. static int do_fclose( struct outfile *of )
  221. {
  222.     int res;
  223.     
  224.     if ( of->name == atom("stdout") ) return 0;
  225.     if ( of->name == atom("stderr") ) return 0;
  226.     
  227.     if ( of->f ) 
  228.         res = fclose( of->f );
  229.     else
  230.         res = 0;
  231.     
  232.     return res;
  233. }
  234.  
  235. static int closefile( void *p )
  236. {
  237.     int i;
  238.     
  239.     struct outfile *of = (struct outfile*)p;
  240.     if ( !of ) return -1;
  241.     if ( of->embed ) return 0; 
  242.  
  243.     for ( i=0; i<of->count; i++ ) 
  244.         if ( writeln( of, of->data + i ) ) return -1;
  245.     
  246.     return do_fclose( of );
  247. }
  248.  
  249. int closeout( void )
  250. {
  251.     return h_foreach( otab, closefile ); 
  252. }
  253.